home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2009 February / PCWFEB09.iso / Software / Freeware / Griffith 0.9.8 / griffith-0.9.8-win32.exe / {app} / lib / plugins / movie / PluginMovieAmazon.py < prev    next >
Text File  |  2008-11-17  |  14KB  |  446 lines

  1. # -*- coding: UTF-8 -*-
  2.  
  3. __revision__ = '$Id$'
  4.  
  5. # Copyright (c) 2006-2008
  6. #
  7. # This program is free software; you can redistribute it and/or modify
  8. # it under the terms of the GNU General Public License as published by
  9. # the Free Software Foundation; either version 2 of the License, or
  10. # (at your option) any later version.
  11. #
  12. # This program is distributed in the hope that it will be useful,
  13. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15. # GNU Library General Public License for more details.
  16. #
  17. # You should have received a copy of the GNU General Public License
  18. # along with this program; if not, write to the Free Software
  19. # 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
  20.  
  21. # You may use and distribute this software under the terms of the
  22. # GNU General Public License, version 2 or later
  23.  
  24. import gutils
  25. import movie
  26. import string
  27. import re
  28. import amazon
  29. import gdebug
  30. import threading
  31. import gtk
  32. from operator import isSequenceType
  33. from urlparse import urlsplit
  34.  
  35. plugin_name = "Amazon"
  36. plugin_description = "Amazon"
  37. plugin_url = "www.amazon.com/.uk/.de/.ca/.fr/.jp"
  38. plugin_language = _("International")
  39. plugin_author = "Michael Jahn"
  40. plugin_author_email = "<mikej06@hotmail.com>"
  41. plugin_version = "1.0"
  42.  
  43. class Plugin(movie.Movie):
  44.  
  45.     def __init__(self, id):
  46.         self.encode='utf8'
  47.         self.movie_id = id
  48.         self.url = 'http://www.amazon.de/dp/' + str(self.movie_id)
  49.  
  50.     def open_page(self, parent_window=None, url=None):
  51.         # dont use base functionality
  52.         # use the Amazon Web API
  53.         self.parent_window = parent_window
  54.         try:
  55.             locale = self.config.get('amazon_locale', 0, section='add')
  56.             if locale == '1':
  57.                 locale = 'uk'
  58.             elif locale == '2':
  59.                 locale = 'de'
  60.             elif locale == '3':
  61.                 locale = 'ca'
  62.             elif locale == '4':
  63.                 locale = 'fr'
  64.             elif locale == '5':
  65.                 locale = 'jp'
  66.             else:
  67.                 locale = None
  68.             retriever = AmazonRetriever(self.movie_id, locale, parent_window, self.progress, self.debug, 'Get')
  69.             retriever.start()
  70.             while retriever.isAlive():
  71.                 self.progress.pulse()
  72.                 while gtk.events_pending():
  73.                     gtk.main_iteration()
  74.             self.page = retriever.result.Item
  75.         except:
  76.             self.page = ''
  77.             try:
  78.                 self.debug.show("Error retrieving results from amazon.")
  79.                 self.debug.show(retriever.result.Request.Errors.Error.Message)
  80.             except:
  81.                 pass
  82.         return self.page
  83.  
  84.     def get_image(self):
  85.         self.image_url = ''
  86.         if hasattr(self.page, 'LargeImage'):
  87.             self.image_url = self.page.LargeImage.URL
  88.         elif hasattr(self.page, 'MediumImage'):
  89.             self.image_url = self.page.MediumImage.URL
  90.         elif hasattr(self.page, 'SmallImage'):
  91.             self.image_url = self.page.SmallImage.URL
  92.  
  93.     def get_o_title(self):
  94.         if hasattr(self.page.ItemAttributes, 'Title'):
  95.             self.o_title = self.page.ItemAttributes.Title
  96.         else:
  97.             self.director = ''
  98.  
  99.     def get_title(self):
  100.         if hasattr(self.page.ItemAttributes, 'Title'):
  101.             self.title = self.page.ItemAttributes.Title
  102.         else:
  103.             self.director = ''
  104.  
  105.     def get_director(self):
  106.         if hasattr(self.page.ItemAttributes, 'Director'):
  107.             self.director = self.page.ItemAttributes.Director
  108.         else:
  109.             self.director = ''
  110.  
  111.     def get_plot(self):
  112.         self.plot = ''
  113.         if hasattr(self.page, 'EditorialReviews'):
  114.             if hasattr(self.page.EditorialReviews, 'EditorialReview'):
  115.                 if isSequenceType(self.page.EditorialReviews.EditorialReview):
  116.                     for review in self.page.EditorialReviews.EditorialReview:
  117.                         if string.find(review.Source, 'Amazon') > -1:
  118.                             self.plot = review.Content
  119.                 else:
  120.                     if hasattr(self.page.EditorialReviews.EditorialReview, 'Source') and \
  121.                         hasattr(self.page.EditorialReviews.EditorialReview, 'Content') and \
  122.                         string.find(self.page.EditorialReviews.EditorialReview.Source, 'Amazon') > -1:
  123.                         self.plot = self.page.EditorialReviews.EditorialReview.Content
  124.  
  125.     def get_year(self):
  126.         if hasattr(self.page.ItemAttributes, 'TheatricalReleaseDate'):
  127.             self.year = self.page.ItemAttributes.TheatricalReleaseDate[:4]
  128.         elif hasattr(self.page.ItemAttributes, 'ReleaseDate'):
  129.             self.year = self.page.ItemAttributes.ReleaseDate[:4]
  130.         else:
  131.             self.year = ''
  132.  
  133.     def get_runtime(self):
  134.         if hasattr(self.page.ItemAttributes, 'RunningTime'):
  135.             self.runtime = self.page.ItemAttributes.RunningTime
  136.         else:
  137.             self.runtime = ''
  138.  
  139.     def get_genre(self):
  140.         # BrowseNodeId 547664 (Genres)
  141.         self.genre = ''
  142.         delimiter = ''
  143.         if hasattr(self.page, 'BrowseNodes') and hasattr(self.page.BrowseNodes, 'BrowseNode'):
  144.             if isSequenceType(self.page.BrowseNodes.BrowseNode):
  145.                 for node in self.page.BrowseNodes.BrowseNode:
  146.                     parentnode = node
  147.                     while hasattr(parentnode, 'Ancestors') and parentnode.BrowseNodeId <> '547664' \
  148.                             and parentnode.BrowseNodeId <> '13628901': # no production countries; they are also arranged under genres
  149.                         parentnode = parentnode.Ancestors.BrowseNode
  150.                     if parentnode.BrowseNodeId == '547664':
  151.                         self.genre = self.genre + delimiter + node.Name
  152.                         delimiter = ', '
  153.  
  154.     def get_cast(self):
  155.         self.cast = ''
  156.         if hasattr(self.page.ItemAttributes, 'Actor'):
  157.             for actor in self.page.ItemAttributes.Actor:
  158.                 self.cast += actor + '\n'
  159.  
  160.     def get_classification(self):
  161.         if hasattr(self.page.ItemAttributes, 'AudienceRating'):
  162.             self.classification = self.page.ItemAttributes.AudienceRating
  163.         else:
  164.             self.classification = ''
  165.  
  166.     def get_studio(self):
  167.         if hasattr(self.page.ItemAttributes, 'Studio'):
  168.             self.studio = self.page.ItemAttributes.Studio
  169.         else:
  170.             self.studio = ''
  171.  
  172.     def get_o_site(self):
  173.         self.o_site = ''
  174.  
  175.     def get_site(self):
  176.         if hasattr(self.page, 'DetailPageURL'):
  177.             parts = urlsplit(self.page.DetailPageURL)
  178.             self.site = parts[0] + '://' + parts[1] + '/dp/' + self.movie_id
  179.         else:
  180.             self.site = ''
  181.  
  182.     def get_trailer(self):
  183.         self.trailer = ''
  184.  
  185.     def get_country(self):
  186.         # BrowseNodeId 13628901 (production countries)
  187.         self.country = ''
  188.         delimiter = ''
  189.         if hasattr(self.page, 'BrowseNodes') and hasattr(self.page.BrowseNodes, 'BrowseNode'):
  190.             if isSequenceType(self.page.BrowseNodes.BrowseNode):
  191.                 for node in self.page.BrowseNodes.BrowseNode:
  192.                     parentnode = node
  193.                     while hasattr(parentnode, 'Ancestors') and parentnode.BrowseNodeId <> '13628901':
  194.                         parentnode = parentnode.Ancestors.BrowseNode
  195.                     if parentnode.BrowseNodeId == '13628901':
  196.                         self.country = self.country + delimiter + node.Name
  197.                         delimiter = ', '
  198.  
  199.     def get_rating(self):
  200.         self.rating = '0'
  201.         if hasattr(self.page, 'CustomerReviews') and \
  202.             hasattr(self.page.CustomerReviews, 'AverageRating'):
  203.             try:
  204.                 tmp_float = float(self.page.CustomerReviews.AverageRating)
  205.                 tmp_float = round(2 * tmp_float, 0)
  206.                 self.rating = str(tmp_float)
  207.             except:
  208.                 pass
  209.  
  210.     def get_notes(self):
  211.         self.notes = ''
  212.         if hasattr(self.page.ItemAttributes, 'EAN'):
  213.             self.notes = 'EAN: ' + self.page.ItemAttributes.EAN
  214.  
  215.  
  216. class SearchPlugin(movie.SearchMovie):
  217.  
  218.     def __init__(self):
  219.         self.original_url_search   = 'http://www.amazon.de'
  220.         self.translated_url_search = 'http://www.amazon.de'
  221.         self.encode='utf8'
  222.         self.remove_accents = False
  223.  
  224.     def search(self,parent_window):
  225.         # dont use base functionality
  226.         # use the Amazon Web API
  227.         self.titles = [""]
  228.         self.ids = [""]
  229.         try:
  230.             locale = self.config.get('amazon_locale', 0, section='add')
  231.             if locale == '1':
  232.                 locale = 'uk'
  233.             elif locale == '2':
  234.                 locale = 'de'
  235.             elif locale == '3':
  236.                 locale = 'ca'
  237.             elif locale == '4':
  238.                 locale = 'fr'
  239.             elif locale == '5':
  240.                 locale = 'jp'
  241.             else:
  242.                 locale = None
  243.             retriever = AmazonRetriever(self.title.encode('iso8859-1'), locale, parent_window, self.progress, self.debug)
  244.             retriever.start()
  245.             while retriever.isAlive():
  246.                 self.progress.pulse()
  247.                 while gtk.events_pending():
  248.                     gtk.main_iteration()
  249.             self.page = retriever.result
  250.         except:
  251.             try:
  252.                 self.debug.show("Error retrieving results from amazon.")
  253.                 self.debug.show(retriever.result.Request.Errors.Error.Message)
  254.             except:
  255.                 pass
  256.         return self.page
  257.  
  258.     def get_searches(self):
  259.         for result in self.page:
  260.             if hasattr(result, 'Item'):
  261.                 if hasattr(result.Item, 'ASIN'):
  262.                     self.add_item(result.Item)
  263.                 else:
  264.                     for item in result.Item:
  265.                         self.add_item(item)
  266.             elif hasattr(result, 'Items'):
  267.                 if hasattr(result.Item, 'ASIN'):
  268.                     self.add_item(result.Items)
  269.                 else:
  270.                     for item in result.Items:
  271.                         self.add_item(item)
  272.  
  273.     def add_item(self, item):
  274.         self.ids.append(item.ASIN)
  275.         if hasattr(item.ItemAttributes, 'ProductGroup'):
  276.             productGroup = item.ItemAttributes.ProductGroup + ' - '
  277.         else:
  278.             productGroup = ''
  279.         if hasattr(item.ItemAttributes, 'Title'):
  280.             title = item.ItemAttributes.Title
  281.         else:
  282.             title = ''
  283.         if hasattr(item.ItemAttributes, 'TheatricalReleaseDate'):
  284.             theatricalReleaseDate = ' (' + item.ItemAttributes.TheatricalReleaseDate + ')'
  285.         else:
  286.             theatricalReleaseDate = ''
  287.         self.titles.append("%s%s%s" % (productGroup, title, theatricalReleaseDate))
  288.  
  289. class AmazonRetriever(threading.Thread):
  290.  
  291.     def __init__(self, title, locale, parent_window, progress, debug, lookuptype='Search', destination=None):
  292.         self.title = title
  293.         self.locale = locale
  294.         self.result = None
  295.         self.destination = destination
  296.         self.parent_window = parent_window
  297.         self.progress = progress
  298.         self.debug = debug
  299.         # Search or Get
  300.         self.lookuptype = lookuptype
  301.         self._stopevent = threading.Event()
  302.         self._sleepperiod = 1.0
  303.         threading.Thread.__init__(self, name='Retriever')
  304.  
  305.     def run(self):
  306.         if self.lookuptype == 'Get':
  307.             self.run_get()
  308.         else:
  309.             self.run_search()
  310.  
  311.     def run_search(self):
  312.         self.result = []
  313.         try:
  314.             amazon.setLicense('04GDDMMXX8X9CJ1B22G2')
  315.             try:
  316.                 tmp = amazon.searchByTitle(self.title, type='ItemAttributes', product_line='Video', locale=self.locale, page=1)
  317.                 self.result.append(tmp)
  318.                 if hasattr(tmp, 'TotalPages'):
  319.                     pages = int(tmp.TotalPages) - 1
  320.                     page = 2
  321.                     while page < pages and page < 11:
  322.                         tmp = amazon.searchByTitle(self.title, type='ItemAttributes', product_line='Video', locale=self.locale, page=page)
  323.                         self.result.append(tmp)
  324.                         page = page + 1
  325.             except amazon.AmazonError, e:
  326.                 self.debug.show(e.Message)
  327.             # if all digits then try to find an EAN / UPC
  328.             if self.title.isdigit():
  329.                 if len(self.title) == 13:
  330.                     try:
  331.                         tmp = amazon.searchByEAN(self.title, type='ItemAttributes', product_line='Video', locale=self.locale)
  332.                         self.result.append(tmp)
  333.                     except amazon.AmazonError, e:
  334.                         self.debug.show(e.Message)
  335.                 elif len(self.title) == 12:
  336.                     try:
  337.                         tmp = amazon.searchByUPC(self.title, type='ItemAttributes', product_line='Video', locale=self.locale)
  338.                         self.result.append(tmp)
  339.                     except amazon.AmazonError, e:
  340.                         self.debug.show(e.Message)
  341.         except IOError:
  342.             self.progress.dialog.hide()
  343.             gutils.urllib_error(_('Connection error'), self.parent_window)
  344.             self.suspend()
  345.  
  346.     def run_get(self):
  347.         self.result = None
  348.         try:
  349.             amazon.setLicense('04GDDMMXX8X9CJ1B22G2')
  350.             # get by ASIN
  351.             try:
  352.                 self.result = amazon.searchByASIN(self.title, type='Large', locale=self.locale)
  353.             except amazon.AmazonError, e:
  354.                 self.debug.show(e.Message)
  355.         except IOError:
  356.             self.progress.dialog.hide()
  357.             gutils.urllib_error(_('Connection error'), self.parent_window)
  358.             self.suspend()
  359.  
  360. #
  361. # Plugin Test
  362. #
  363. class SearchPluginTest(SearchPlugin):
  364.     #
  365.     # Configuration for automated tests:
  366.     # dict { movie_id -> [ expected result count for original url, expected result count for translated url ] }
  367.     #
  368.     test_configuration = {
  369.         'Rocky Balboa'            : [ 10, 10 ],
  370.         'Arahan'                : [ 6, 6 ],
  371.         'Ein gl├╝ckliches Jahr'    : [ 2, 2 ]
  372.     }
  373.  
  374. class PluginTest:
  375.     #
  376.     # Configuration for automated tests:
  377.     # dict { movie_id -> dict { arribute -> value } }
  378.     #
  379.     # value: * True/False if attribute only should be tested for any value
  380.     #        * or the expected value
  381.     #
  382.     test_configuration = {
  383.         'B000TIQMMI' : { 
  384.             'title'             : 'Rocky Balboa',
  385.             'o_title'             : 'Rocky Balboa',
  386.             'director'            : '',
  387.             'plot'                 : True,
  388.             'cast'                : 'Sylvester Stallone\n\
  389. Antonio Traver\n\
  390. Burt Young',
  391.             'country'            : 'USA',
  392.             'genre'                : 'Mehr Drama, Drama',
  393.             'classification'    : 'Freigegeben ab 12 Jahren',
  394.             'studio'            : 'MGM Home Entertainment GmbH (dt.)',
  395.             'o_site'            : False,
  396.             'site'                : 'http://www.amazon.de/dp/B000TIQMMI',
  397.             'trailer'            : False,
  398.             'year'                : 2006,
  399.             'notes'                : 'EAN: 4045167004504',
  400.             'runtime'            : 97,
  401.             'image'                : True,
  402.             'rating'            : 9
  403.         },
  404.         'B0009NSASM' : { 
  405.             'title'             : 'Ein gl├╝ckliches Jahr',
  406.             'o_title'             : 'Ein gl├╝ckliches Jahr',
  407.             'director'            : 'Claude Lelouch',
  408.             'plot'                 : False,
  409.             'cast'                : 'Lino Ventura\n\
  410. Fran├ºoise Fabian\n\
  411. Charles G├⌐rard',
  412.             'country'            : 'Frankreich, Italien',
  413.             'genre'                : 'Krimi, Mehr Drama, Mehr Kom├╢die, Drama, Kom├╢die, Krimi',
  414.             'classification'    : 'Freigegeben ab 12 Jahren',
  415.             'studio'            : 'Warner Home Video - DVD',
  416.             'o_site'            : False,
  417.             'site'                : 'http://www.amazon.de/dp/B0009NSASM',
  418.             'trailer'            : False,
  419.             'year'                : 1973,
  420.             'notes'                : 'EAN: 7321921998843',
  421.             'runtime'            : 110,
  422.             'image'                : True,
  423.             'rating'            : 10
  424.         },
  425.         'B000BSNOD6' : { 
  426.             'title'             : 'Arahan (Vanilla-DVD)',
  427.             'o_title'             : 'Arahan (Vanilla-DVD)',
  428.             'director'            : 'Ryoo Seung-wan',
  429.             'plot'                 : False,
  430.             'cast'                : 'Ryu Seung-beom\n\
  431. Yoon So-yi\n\
  432. Ahn Sung-kee',
  433.             'country'            : 'S├╝dkorea',
  434.             'genre'                : 'Actionkom├╢die, Abenteuer- & Actionkom├╢die, Fantasykom├╢die, Action, Kom├╢die, Mehr Fantasy, Korea, Action, Kom├╢die, Fantasy, Unter 10 EUR',
  435.             'classification'    : 'Freigegeben ab 16 Jahren',
  436.             'o_site'            : False,
  437.             'site'                : 'http://www.amazon.de/dp/B000BSNOD6',
  438.             'trailer'            : False,
  439.             'year'                : 2005,
  440.             'notes'                : 'EAN: 4013549871105',
  441.             'runtime'            : 108,
  442.             'image'                : True,
  443.             'rating'            : 8
  444.         }
  445.     }
  446.